# -*- coding: utf-8 -*-
from httplib import *
import hashlib
from xml.dom.minidom import *
import re
import urllib
from PyKDE4.phonon import Phonon
from PyQt4.QtCore import *
from PyQt4.QtNetwork import *
from lastfm import LastFMConnection, LastFMTrack, LastFMError

class LastFMConnectionQt(LastFMConnection, QObject):

	def __init__(self, debug = False):

		QObject.__init__(self)
		LastFMConnection.__init__(self, debug)

		self.connection = QHttp('ws.audioscrobbler.com')
		self.connect(self.connection, SIGNAL('responseHeaderReceived(QHttpResponseHeader)'), self.processHeader)

	# This method is to be called first, when there is no session
	# key yet.

	def requestToken(self):

		url = self.buildUrl({'method':'auth.getToken', 'api_key':self.apiKey})
		#self.ensureConnection()
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processToken)
		self.httpGet(url)
		
	def processToken(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processToken)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('tokenFailure(QString)'), 'HTTP GET Failed')
		else:
	
			dom = parseString(self.httpBody())
			try:

				self.token = self.extractXMLValues(dom, 'lfm/token')[0]
			except IndexError:

				self.emit(SIGNAL('tokenFailure(QString)'), 'Could not extract token from response.')
			else:

				link = 'http://www.last.fm/api/auth/?api_key='+self.apiKey+'&token='+self.token
				self.emit(SIGNAL('tokenSuccess(QString)'), link)

	# This method will only work after requestToken() has been sucessfully
	# called, and permission has been granted on the last.fm website.

	def requestSession(self):
	
		url = self.buildUrl({'api_key':self.apiKey, 'method':'auth.getSession', 'token':self.token})		
		#self.ensureConnection()
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processSession)
		self.httpGet(url)
		
	def processSession(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processSession)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('sessionFailure(QString)'), 'HTTP GET Failed')
		else:
	
			dom = parseString(self.httpBody())
			try:

				self.sessionKey = self.extractXMLValues(dom, 'lfm/session/key')[0]
			except IndexError:

				self.emit(SIGNAL('sessionFailure(QString)'), 'Could not extract session key from response.')
			else:

				self.emit(SIGNAL('sessionSuccess(QString)'), self.sessionKey)

	# this method can be called if there is a session key available.

	def requestStation(self, station):

		params = {'method':'radio.tune', 'station':station, 'api_key':self.apiKey, 'sk':self.sessionKey}
		self.addApiSignature(params)
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processStation)
		self.httpPost(params)

	def processStation(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processStation)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('stationFailure(QString)'), 'HTTP POST Failed. This could mean that the station you tried to tune in does not exist or that you are not allowed to stream from last.fm (only paying subscribers are).')
		else:
	
			self.emit(SIGNAL('stationSuccess()'))

	# this method can be called, after a station was set correctly

	def requestTracks(self):

		url = self.buildUrl({'method':'radio.getPlaylist', 'api_key':self.apiKey, 'sk':self.sessionKey})
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processTracks)
		self.httpGet(url)

	def processTracks(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processTracks)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('tracksFailure(QString)'), 'HTTP POST Failed')
		else:
	
			dom = parseString(self.httpBody())
			locations = self.extractXMLValues(dom, 'playlist/trackList/track*/location')
			titles = self.extractXMLValues(dom, 'playlist/trackList/track*/title')
			creators = self.extractXMLValues(dom, 'playlist/trackList/track*/creator')
			images = self.extractXMLValues(dom, 'playlist/trackList/track*/image')
			tracks = list()

			for location, title, creator, image in zip(locations, titles, creators, images):
				
				track = LastFMTrack(location)
				track.title = title
				track.artist = creator
				track.art = image
				tracks.append(track)
			self.emit(SIGNAL('tracksSuccess(PyQt_PyObject)'), tracks)

	# convenience methods

	def buildUrl(self, params):

		self.addApiSignature(params)
		return '/2.0/?'+urllib.urlencode(params)

	# http methods

	def processHeader(self, header):

		self.responseHeader = header
		if self.debug:

			print header.statusCode(), header.reasonPhrase()

	def httpGet(self, url):

		self.buffer = QBuffer()
		self.connection.get(url, self.buffer)

	def httpPost(self, params):

		data = QByteArray(urllib.urlencode(params))
		header = QHttpRequestHeader('POST', '/2.0/')
		header.setContentType('application/x-www-form-urlencoded')
		header.setValue('Host', 'ws.audioscrobbler.com')
		self.buffer = QBuffer()
		self.connection.request(header, urllib.urlencode(params), self.buffer)

	def httpBody(self):

		body = self.buffer.data()
		if self.debug:

			print body
		return body
